<?php

namespace app\common\cachemodel\zlcr3;

use app\chat\LiveMessage;
use app\common\cachemodel\ZhunleUserAccount;
use app\common\cachemodel\ZhunleUserAccountRecord;
use app\common\cachemodel\ZlcrAstr;
use app\common\cachemodel\ZlcrAstrAccount;
use app\common\lib\exception\ApiException;
use app\common\lib\Util;
use app\common\model\BaseCache;
use app\common\model\User;
use think\Db;
use think\Log;
use XznsTools\cache\CacheManage;

class Zlcr3ConsultChatRtcRecord extends BaseCache
{
    protected $table = 'wechat_backup_07_18_14_43_00.zlcr3_consult_chat_rtc_record';

    protected $cacheModel = 'voice_consult.chat_rtc';

    /**
     * 用户咨询列表
     * @param $uid
     * @return array|mixed
     * @throws \Exception
     */
    public function userRtcChat($uid)
    {
        $data = (new Zlcr3ConsultChatRtcRecord())->getListPage($uid);
        $astrIds = array_values(array_unique(array_column($data['data'], 'astr_id')));
        $astrInfos = (new ZlcrAstr())->batchGetInfoByIds($astrIds, ['nickname', 'avatar', 'extend']);
        $res = [];
        foreach ($data['data'] as $item)
        {
            $res[] = [
                'id' => $item['chat_detail_id'] ?? 0,
                'avatar' => $astrInfos[$item['astr_id']]['avatar'],
                'name' => $astrInfos[$item['astr_id']]['nickname'],
                'list' => [
                    [
                        'title' => '服务编号',
                        'des' => $item['chat_detail_id'] ?? 0,
                        'type' => 2
                    ],
                    [
                        'title' => '连线时长',
                        'des' => gmdate("H:i:s", $item['duration']),
                        'type' => 1
                    ],
                    [
                        'title' => '连线消耗',
                        'des' => $item['coin'] . '准币',
                        'type' => 1
                    ],
                    [
                        'title' => '接通时间',
                        'des' => date('Y-m-d H:i:s', $item['start_time']),
                        'type' => 1
                    ]
                ]
            ];
        }
        $data['data'] = $res;
        return $data;
    }

    /**
     *  写入 连线数据
     * @param $data
     * @return int
     */
    public function SaveData($data)
    {
        try
        {
            if (isset($data['extend']))
            {
                $data['extend'] = json_encode($data['extend'], JSON_UNESCAPED_UNICODE);
            }

            $id = $this->insertGetId($data);

            return (int)$id;
        }
        catch (\Exception $e)
        {
            \think\Log::write(__CLASS__ . ' => ' . __FUNCTION__ . '()异常：' . $e->getMessage() . '失败信息：' . $e->getFile() . ':' . $e->getLine(), 'error', true);
            return 0;
        }
    }

    /**
     * 更新 RTC 信息
     * @param int $id
     * @param int $uid
     * @param array $data
     * @param int $actionType 操作类型 1=>更新消耗准币信息｜连麦状态  2=>挂断
     * @return bool
     */
    public function updateData(int $id, int $uid, array $data, int $actionType)
    {
        try
        {   //
            if (isset($data['extend']))
            {
                $data['extend'] = json_encode($data['extend'], JSON_UNESCAPED_UNICODE);
            }

            $this->where(['id' => $id])->update($data);

            if ($actionType === 2)
            {   // 挂断的时候 添加到连线列表
                $this->listDataAdd($uid, [$id => $id]);
            }
            CacheManage::getInstance()->setCacheConfig($this->cacheModel, $id)->rmCache();
            return true;
        }
        catch (\Exception $e)
        {
            \think\Log::write(__CLASS__ . ' => ' . __FUNCTION__ . '()异常：' . $e->getMessage() . '失败信息：' . $e->getFile() . ':' . $e->getLine(), 'error', true);
            return false;
        }
    }

    /**
     * @param array $ids
     * @param array|null $type
     * @param string $sortType
     * @return array
     */
    public function getInfoByIdsInData($ids, $type, $sortType)
    {
        if ($ids)
        {   // 获取未删除 的数据
            $where = ['id' => ['in', $ids]];
        } else
        {   // 获取指定pid  未删除 且 未隐藏的数据
            $where = ['uid' => $type[0]];
        }
        $field = 'uid,chat_detail_id,astr_id,status,type,is_recommend,is_comment,duration,test_duration,eff_duration,unit_price,coin,astr_earning,extend,create_time,start_time,end_time';
        try
        {
            $data = $this
                ->field($field)
                ->where($where)
                ->column($field, 'id');
        }
        catch (\Exception $e)
        {
            $data = [];
        }
        return $data;
    }

    public function batchGetInfoByIds($cids, $field = [])
    {
        $resData = parent::batchGetInfoByIds($cids, $field);

        return $this->dataInit($resData);
    }

    /**
     * 数据初始化
     * @param array $data
     * @return array
     */
    public function dataInit(array $data)
    {
        foreach ($data as $index => $itemData)
        {
            $data[$index] = arrayKeyData2int($itemData, ['id', 'chat_detail_id', 'astr_id', 'uid', 'status', 'type', 'duration', 'is_recommend', 'is_comment', 'test_duration', 'eff_duration', 'unit_price', 'coin', 'create_time', 'start_time', 'end_time']);

            if (isset($itemData['extend']))
            {
                $data[$index]['extend'] = $itemData['extend'] ? json_decode($itemData['extend'], true) : [];
            }
        }

        return $data;
    }

    /**
     * 保存当前连麦数据 到缓存
     * @param int $type 1 =>用户   2=>占星师
     * @param int $id
     * @param array $data
     * @param bool $isUpdate
     * @return bool
     */
    public function saveNowRtcDataToCache(int $type, int $id, array $data, bool $isUpdate = false)
    {
        try
        {
            if (isset($data['recode_datas']))
            {
                $data['recode_datas'] = json_encode($data['recode_datas'], true);
            }

            if (isset($data['dice_datas']))
            {
                $data['dice_datas'] = json_encode($data['dice_datas'], true);
            }

            if (isset($data['tarot_datas']))
            {
                $data['tarot_datas'] = json_encode($data['tarot_datas'], true);
            }

            $cacheId = ($type === 1 ? 'user:' : 'astro:') . $id;
            CacheManage::getInstance()->setCacheConfig($this->cacheModel)->setCacheKeyDetail('now_rtc', $cacheId)->setCache($data, 'now_rtc', $isUpdate);
        }
        catch (\Exception $e)
        {
            Log::write('更新当前咨询连麦数据 到缓存失败:' . $e->getMessage(), 'error');
            return false;
        }

        return true;
    }

    /**
     * 从缓存中 获取当前连麦数据
     * @param int $type 1 =>用户   2=>占星师
     * @param int $id
     * @param array $filed
     * @return bool|array|string
     */
    public function getNowRtcDataByCache(int $type, int $id, array $filed = [])
    {
        try
        {
            $cacheId = ($type === 1 ? 'user:' : 'astro:') . $id;
            $data = CacheManage::getInstance()->setCacheConfig($this->cacheModel)->setCacheKeyDetail('now_rtc', $cacheId)->getCache($filed, 'now_rtc');

            if ($data)
            {
                $data = arrayKeyData2int($data, ['id', 'astr_id', 'uid', 'status', 'request_time', 'chat_id', 'user_rtc_online', 'astr_rtc_online']);

                if (isset($data['recode_datas']))
                {
                    $data['recode_datas'] = $data['recode_datas'] ? json_decode($data['recode_datas'], true) : [];
                }

                if (isset($data['dice_datas']))
                {
                    $data['dice_datas'] = $data['dice_datas'] ? json_decode($data['dice_datas'], true) : [];
                }

                if (isset($data['tarot_datas']))
                {
                    $data['tarot_datas'] = $data['tarot_datas'] ? json_decode($data['tarot_datas'], true) : [];
                }
            }

            return $data;
        }
        catch (\Exception $e)
        {
            Log::write('获取当前咨询连麦数据 到缓存失败:' . $e->getMessage(), 'error');
            return false;
        }
    }

    /**
     * 从缓存中 删除当前连麦数据
     * @param int $type 1 =>用户   2=>占星师
     * @param int $id
     * @return bool
     */
    public function delNowRtcDataByCache(int $type, int $id)
    {
        try
        {
            $cacheId = ($type === 1 ? 'user:' : 'astro:') . $id;
            CacheManage::getInstance()->setCacheConfig($this->cacheModel)->setCacheKeyDetail('now_rtc', $cacheId)->rmCache('now_rtc');
        }
        catch (\Exception $e)
        {
            Log::write('删除咨询当前连麦数据 到缓存失败:' . $e->getMessage(), 'error');
            return false;
        }
        return true;
    }

    /**
     * 获取 RTC 操作 加锁 2秒的锁
     * @param int $chatDetailId
     * @return bool 加锁成功=>true    加锁失败=>false   加锁成功允许进行后续操作 否则禁止进行后续操作
     * @throws \RedisException
     */
    public function setRtcPadlock(int $chatDetailId)
    {
        $cache = CacheManage::getInstance()->setCacheConfig($this->cacheModel)->setCacheKeyDetail('rtc_padlock', $chatDetailId);
        $redis = $cache->redisHandler;

        $num = $redis->incr($cache->cacheKey['rtc_padlock']);
        if ($num === 1)
        {
            $redis->expire($cache->cacheKey['rtc_padlock'], 2);
            return true;
        } else
        {
            return false;
        }
    }

    /**
     * 删除之前 加的锁
     */
    public function loseOperatorLicense(int $chatDetailId)
    {
        CacheManage::getInstance()->setCacheConfig($this->cacheModel)->setCacheKeyDetail('rtc_padlock', $chatDetailId)->rmCache('rtc_padlock');
    }

    /**
     * @param array $astrNowConsultRtcInfo
     * @param int $type 1=>获取用户端显示信息 2=>获取咨询师端显示信息
     * @return array[]
     */
    public function resetRtcConsultStatusData(array $astrNowConsultRtcInfo, int $type = 1)
    {
        $recodeDatas = $astrNowConsultRtcInfo['recode_datas'] ?? [];
        foreach ($recodeDatas as $k => $recodeItemData)
        {
            if ($type === 2)
            {
                $recodeDatas[$k]['comments'] = $recodeItemData['user_des'];
            }
            unset($recodeDatas[$k]['user_des']);
        }

        $isHuaweiOrOppo = Util::IsHuaweiAndOppo();
        return [
            [
                'type' => 1,
                'icon' => '/test/rtc_consult/astr_icon.png',
                'title' => '星盘',
                'des' => '根据咨询师的要求提供档案',
                'recode_datas' => $recodeDatas,
            ], [
                'type' => 2,
                'icon' => '/test/rtc_consult/dice_icon.png',
                'title' => '骰子',
                'des' => '根据咨询师的要求掷出骰子',
                'dice_datas' => $astrNowConsultRtcInfo['dice_datas'] ?? [],
            ], [
                'type' => 3,
                'icon' => '/test/rtc_consult/tarot_icon.png',
                'title' => $isHuaweiOrOppo ? '卡牌' : '塔罗',
                'des' => '根据咨询师的要求抽取' . ($isHuaweiOrOppo ? '卡牌' : '塔罗牌'),
                'tarot_datas' => $astrNowConsultRtcInfo['tarot_datas'] ?? [],
            ],
        ];
    }

    /**
     * RTC 连线咨询 挂断
     * @param array $chatDetail
     * @param string $reason 故障挂断 原因
     * @param int $userType 挂断用户  1=>用户 2=>咨询师
     * @param int $hangUpType 挂断类型 1=>主动挂断【 用户｜咨询师 主动挂断 】 2=>被动挂断【 rtc离线｜队列扣费准币不足 】
     * @return array
     * @throws ApiException
     */
    public function rtcConsultHangUp(array $chatDetail, string $reason, int $userType = 1, int $hangUpType = 1)
    {
        $nowTime = time();
        $chatDetailId = $chatDetail['id'];
        // 挂断
        $rtcInfo = $this->getInfoById($chatDetail['extend']['rtc_data']['rtc_id']);
        if (in_array($rtcInfo['status'], [4, 5, 6], true))
        {
            return ['status' => false, 'data' => [], 'msg' => '连线已挂断',];
        }
        $rtcInfoUpdate = [
            'type' => 2,
            'end_time' => $nowTime,
            'extend' => $rtcInfo['extend'],
            'duration' => 0
        ];
        if ($rtcInfo['status'] === 2)
        {   // 连接中
            $rtcInfoUpdate['status'] = 6;
        } else
        {   // 语音咨询中
            $duration = $nowTime - $rtcInfo['start_time'];
            if ($duration < 60)
            {
                if ($hangUpType === 1 && empty($reason))
                {
                    return ['status' => false, 'data' => [], 'msg' => '请选择故障挂断原因～',];
                }
                $rtcInfoUpdate['status'] = 5;
                $rtcInfoUpdate['extend']['reason'] = $reason;   // 故障挂断原因
            } else
            {
                $rtcInfoUpdate['status'] = 4;
            }
            $rtcInfoUpdate['duration'] = $duration;
        }
        // 获取咨询师 当前连麦状态
        $astrNowConsultRtcInfo = $this->getNowRtcDataByCache(2, $rtcInfo['astr_id']);
        if ($astrNowConsultRtcInfo && $astrNowConsultRtcInfo['chat_id'] == $chatDetailId)
        {   // 咨询师 当前连麦 与当前取消的连麦是一致的
            // 记录 咨询信息
            $rtcInfoUpdate['extend']['recode_datas'] = $astrNowConsultRtcInfo['recode_datas'] ?? [];
            $rtcInfoUpdate['extend']['dice_datas'] = $astrNowConsultRtcInfo['dice_datas'] ?? [];
            $rtcInfoUpdate['extend']['tarot_datas'] = $astrNowConsultRtcInfo['tarot_datas'] ?? [];
            // 删除 当前咨询 信息
            $this->delNowRtcDataByCache(2, $rtcInfo['astr_id']);
        }

        if ($rtcInfoUpdate['status'] === 4)
        {   // 正常挂断
            $totalAmount = $rtcInfo['coin'] / 10;
            $zhunleUserAccountModel = new ZhunleUserAccount();
            $userCoin = $zhunleUserAccountModel->getUserCoinFromCache($rtcInfo['uid']);  // 账户信息
            $coinNum = (int)($userCoin['balance'] ?? 0);// 准币余额
            // 写入 用户 准币流水
            $insertData = [
                'status' => 1,
                'account' => 0,
                'uid' => $rtcInfo['uid'],
                'consumer_type' => 2,
                'order_type' => 100,
                'gid' => 0,
                'pray_date' => 0,
                'total_amount' => $totalAmount,
                'coin_num' => $rtcInfo['coin'],
                'balance' => $coinNum,
                'order_id' => '',
                'trade_type' => 4,
                'create_time' => $nowTime,
                'extend' => json_encode(['rtc_id' => $rtcInfo['id']], JSON_UNESCAPED_UNICODE)
            ];
            //增加准币明细记录
            (new ZhunleUserAccountRecord())->SaveData($rtcInfo['uid'], $insertData);
            // 写入占星师 收入
            // 1、 计算咨询师收益
            $totalPrice = ($rtcInfo['coin'] * $rtcInfo['extend']['percent'] * ($rtcInfo['extend']['active_percent'] ?? 1)) / 10;
            $earnings = Util::getAfterTaxAmount($totalPrice);
            (new ZlcrAstrAccount())->astrRtcConsultEarningsSend([
                'earning' => $earnings,
                'total_amount' => $totalAmount, // 用户支付 时间金额
                'astr_id' => $rtcInfo['astr_id'],
                'type' => 1,    // 1=>入账 2=>提现 3=>后台人员回复的用户内容 4=>问答冻结  5=>问答解冻
                'gid' => $rtcInfo['id'],
                'proportion' => $rtcInfo['extend']['percent'],
                'service_duration' => $rtcInfoUpdate['duration'],
            ]);
            if ($rtcInfoUpdate['duration'] - $rtcInfo['test_duration'] > 0)
            {   // 计价时长
                $rtcInfoUpdate['eff_duration'] = $rtcInfoUpdate['duration'] - $rtcInfo['test_duration'];
            }

            (new Zlcr3ConsultAstrData())->analysisDataUpdate($rtcInfo['astr_id'], (int)date('YmdH'), [
                'service_duration' => Db::raw("service_duration +" . $rtcInfoUpdate['duration']),
                'service_num' => Db::raw("service_num + 1"),
            ]);

            $rtcInfoUpdate['astr_earning'] = $earnings;
        }
        // 更新了连麦状态
        $this->updateData($rtcInfo['id'], $rtcInfo['uid'], $rtcInfoUpdate, 2);
        // 获取用户当前连麦 状态
        $userNowConsultRtcInfo = $this->getNowRtcDataByCache(1, $rtcInfo['uid']);
        if ($userNowConsultRtcInfo && $userNowConsultRtcInfo['chat_id'] == $chatDetailId)
        {   // 用户当前连麦 是 与当前取消是一致的
            $this->delNowRtcDataByCache(1, $rtcInfo['uid']); // 删除当前连麦信息
        }
        $astrTip = '';
        switch ($rtcInfoUpdate['status'])  //  4=>连麦结束 5=>故障挂断 6=>取消连麦（连接中挂断）
        {
            case 4:
                $durationTime = Util::secondToMinute($rtcInfoUpdate['duration']);
                $astrTip = "连线时长 {$durationTime}，收益{$rtcInfoUpdate['astr_earning']}元";
                $consultInfo = [
                    'status' => 4,
                    'tip' => "连线时长 {$durationTime}，消耗{$rtcInfo['coin']}准币",
                    'target' => 'local',
                    'link' => "rtc_consult_detail?id={$chatDetailId}&need_auth=2",
                ];
                (new Zlcr3ConsultChatRecordAstr())->astroSendUpdate($rtcInfo['uid'], $rtcInfo['astr_id'], [
                    'consult_num' => $this->raw('consult_num +1'), // 有效 咨询次数 +1
                    'consult_coin' => $this->raw('consult_coin +' . $rtcInfo['coin']), // 消耗准币数
                    'last_consult_time' => $rtcInfo['start_time'], // 最后一次有效 咨询 开始 连麦时间
                ]);
                break;
            case 5:
                $consultInfo = [
                    'status' => 4,
                    'tip' => '故障挂断',
                    'target' => 'local',
                    'link' => 'empty',
                ];
                break;
            default:
                $consultInfo = [
                    'status' => 4,
//                    'tip' => $userType === 1 ? '连线已取消' : '咨询师不便接听，稍后重试',
                    'tip' => '连线已取消',
                    'target' => 'local',
                    'link' => 'empty',
                ];
        }
        $userInfo = (new User())->getUserinfo(['id' => $rtcInfo['uid']]);
        $msgData1 = [
            'id' => $chatDetailId,
            'type' => 1,
            'time_des' => '',
            'time' => '',
            'avatar' => $userInfo['avatar'],
            'msg_des' => '连线咨询',
            'tags' => [],
            'consult_info' => $consultInfo,
            'btn_info' => null,
            'content' => '',
            'content_type' => 1,
        ];
        if ($userType === 2 || ($userType === 1 && $hangUpType === 2))
        {   // 向 用户 发送消息
            // 1 连麦消息
            LiveMessage::sendMsg(LiveMessage::who(LiveMessage::WHO_TYPE_UID, 0, $astrNowConsultRtcInfo['uid']), LiveMessage::MSG_TYPE_POP_CONSULT_MSG, [
                'msg_type' => 1,
                'astr_id' => $rtcInfo['astr_id'],
                'msg_data' => $msgData1
            ]);
            if ($rtcInfoUpdate['status'] === 4)
            {   // 结束连麦
                // 2 连麦状态刷新消息
                $consultDetailRefresh = [
                    'target' => 'local',
                    'link' => "alert_consult_question?id={$chatDetailId}&need_auth=2",
                    'force_open' => 1,
                ];
                LiveMessage::sendMsg(LiveMessage::who(LiveMessage::WHO_TYPE_UID, 0, $astrNowConsultRtcInfo['uid']), LiveMessage::MSG_TYPE_POP_CONSULT_DETAIL_REFRESH, $consultDetailRefresh);
            } else
            {   // 故障挂断 ｜ 取消连线
                LiveMessage::sendMsg(LiveMessage::who(LiveMessage::WHO_TYPE_UID, 0, $chatDetail['uid']), LiveMessage::MSG_TYPE_POP_CONSULT_TOAST, [
                    'content' => $rtcInfoUpdate['status'] === 5 ? '故障挂断，连线已取消' : '连接失败，连线已取消'
                ]);
            }
        }
        if ($rtcInfoUpdate['status'] === 6)
        {
            $consultInfo['tip'] = '连线已取消';
        }
        if ($rtcInfoUpdate['status'] === 4)
        {
            $consultInfo['tip'] = $astrTip;
        }
        $msgData2 = [
            'id' => $chatDetailId,
            'type' => 2,
            'time_des' => '',
            'time' => '',
            'avatar' => $userInfo['avatar'],
            'msg_des' => '连线咨询',
            'tags' => [],
            'consult_info' => $consultInfo,
            'btn_info' => $rtcInfoUpdate['status'] === 4 ? [['name' => '查看记录', 'type' => 4, 'id' => 0,]] : null,
            'content' => '',
            'content_type' => 1,
        ];
        if ($userType === 1 || ($userType === 2 && $hangUpType === 2))
        {   // 向咨询师 发送消息
            // 1 连麦消息
            LiveMessage::sendMsg(LiveMessage::who(LiveMessage::WHO_TYPE_ASTRO, 0, $rtcInfo['astr_id']), LiveMessage::MSG_TYPE_POP_CONSULT_MSG, [
                'msg_type' => 2,
                'uid' => $rtcInfo['uid'],
                'msg_data' => $msgData2
            ]);
            if ($rtcInfoUpdate['status'] === 4)
            {   // 结束连麦
                // 2 连麦状态刷新消息
                $consultDetailRefresh = [
                    'target' => 'local',
                    'link' => "alert_consult_question?id={$chatDetailId}&need_auth=2",
                    'force_open' => 1,
                ];
                LiveMessage::sendMsg(LiveMessage::who(LiveMessage::WHO_TYPE_ASTRO, 0, $rtcInfo['astr_id']), LiveMessage::MSG_TYPE_POP_CONSULT_DETAIL_REFRESH, $consultDetailRefresh);
            } else
            {   // 故障挂断 ｜ 取消连线
                LiveMessage::sendMsg(LiveMessage::who(LiveMessage::WHO_TYPE_ASTRO, 0, $rtcInfo['astr_id']), LiveMessage::MSG_TYPE_POP_CONSULT_TOAST, [
                    'content' => $rtcInfoUpdate['status'] === 5 ? '故障挂断，连线已取消' : '连接失败，连线已取消'
                ]);
            }
        }

        return [
            'status' => true,
            'msg' => '',
            'data' => $userType === 1 ? $msgData1 : $msgData2,
        ];
    }
}
